package com.media.system.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.media.system.common.core.controller.BaseController;
import com.media.system.common.core.domain.AjaxResult;
import com.media.system.common.core.page.TableDataInfo;
import com.media.system.common.utils.PageUtils;
import com.media.system.common.utils.StringUtils;
import com.media.system.domain.MediaFile;
import com.media.system.service.MediaFileService;
import com.media.system.service.dto.FileUploadRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 媒体文件管理控制器
 * 
 * @author Claude
 * @since 2024-01-20
 */
@RestController
@RequestMapping("/media")
@Tag(name = "媒体文件管理", description = "媒体文件上传、下载、管理等相关接口")
@Slf4j
public class MediaFileController extends BaseController {

    @Autowired
    private MediaFileService mediaFileService;

    /**
     * 单文件上传
     */
    @PostMapping("/upload")
    @PreAuthorize("hasPermission('media:file:upload')")
    @Operation(summary = "单文件上传", description = "上传单个媒体文件")
    public AjaxResult uploadFile(
            @Parameter(description = "上传文件", required = true) @RequestParam("file") MultipartFile file,
            @Parameter(description = "上传参数") FileUploadRequest request) {
        
        try {
            if (request == null) {
                request = new FileUploadRequest();
            }
            
            MediaFile mediaFile = mediaFileService.uploadFile(file, request);
            return success("文件上传成功", mediaFile);
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            return error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 批量文件上传
     */
    @PostMapping("/batch-upload")
    @PreAuthorize("hasPermission('media:file:upload')")
    @Operation(summary = "批量文件上传", description = "批量上传多个媒体文件")
    public AjaxResult batchUploadFiles(
            @Parameter(description = "上传文件列表", required = true) @RequestParam("files") List<MultipartFile> files,
            @Parameter(description = "上传参数") FileUploadRequest request) {
        
        try {
            if (request == null) {
                request = new FileUploadRequest();
            }
            
            List<MediaFile> mediaFiles = mediaFileService.batchUploadFiles(files, request);
            return success("批量上传完成", mediaFiles);
        } catch (Exception e) {
            log.error("批量文件上传失败: {}", e.getMessage(), e);
            return error("批量文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户媒体文件列表
     */
    @GetMapping("/list")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取媒体文件列表", description = "分页获取当前用户的媒体文件列表")
    public TableDataInfo list(
            @Parameter(description = "文件类型") @RequestParam(value = "fileType", required = false) String fileType) {
        
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.selectMediaFilesByUserId(page, getUserId(), fileType);
        return getDataTable(result);
    }

    /**
     * 搜索媒体文件
     */
    @GetMapping("/search")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "搜索媒体文件", description = "根据关键字搜索媒体文件")
    public TableDataInfo search(
            @Parameter(description = "搜索关键字") @RequestParam("keyword") String keyword) {
        
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.searchMediaFiles(page, getUserId(), keyword);
        return getDataTable(result);
    }

    /**
     * 根据标签查询文件
     */
    @GetMapping("/by-tags")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "根据标签查询文件", description = "根据标签查询媒体文件")
    public TableDataInfo getFilesByTags(
            @Parameter(description = "标签") @RequestParam("tags") String tags) {
        
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.selectMediaFilesByTags(page, getUserId(), tags);
        return getDataTable(result);
    }

    /**
     * 获取最近上传的文件
     */
    @GetMapping("/recent")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取最近上传的文件", description = "获取最近上传的媒体文件")
    public AjaxResult getRecentFiles(
            @Parameter(description = "数量限制") @RequestParam(value = "limit", defaultValue = "10") Integer limit) {
        
        List<MediaFile> files = mediaFileService.getRecentMediaFiles(getUserId(), limit);
        return success(files);
    }

    /**
     * 获取收藏的文件
     */
    @GetMapping("/favorites")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取收藏的文件", description = "获取用户收藏的媒体文件")
    public TableDataInfo getFavoriteFiles() {
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.getFavoriteMediaFiles(page, getUserId());
        return getDataTable(result);
    }

    /**
     * 获取文件详情
     */
    @GetMapping("/{fileId}")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取文件详情", description = "根据文件ID获取文件详细信息")
    public AjaxResult getFileDetail(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId) {
        
        MediaFile mediaFile = mediaFileService.getById(fileId);
        if (mediaFile == null || !mediaFile.getUserId().equals(getUserId())) {
            return error("文件不存在或无权访问");
        }
        
        // 增加查看次数
        mediaFileService.incrementViewCount(fileId);
        
        return success(mediaFile);
    }

    /**
     * 切换文件收藏状态
     */
    @PostMapping("/{fileId}/toggle-favorite")
    @PreAuthorize("hasPermission('media:file:edit')")
    @Operation(summary = "切换收藏状态", description = "切换文件的收藏状态")
    public AjaxResult toggleFavorite(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId) {
        
        boolean result = mediaFileService.toggleFavorite(fileId, getUserId());
        return result ? success("操作成功") : error("操作失败");
    }

    /**
     * 更新文件标签
     */
    @PutMapping("/{fileId}/tags")
    @PreAuthorize("hasPermission('media:file:edit')")
    @Operation(summary = "更新文件标签", description = "更新文件的用户自定义标签")
    public AjaxResult updateFileTags(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId,
            @Parameter(description = "标签", required = true) @RequestParam("tags") String tags) {
        
        boolean result = mediaFileService.updateFileTags(fileId, getUserId(), tags);
        return result ? success("标签更新成功") : error("标签更新失败");
    }

    /**
     * 移动文件到回收站
     */
    @PostMapping("/{fileId}/trash")
    @PreAuthorize("hasPermission('media:file:delete')")
    @Operation(summary = "移动到回收站", description = "将文件移动到回收站")
    public AjaxResult moveToTrash(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId) {
        
        boolean result = mediaFileService.moveToTrash(fileId, getUserId());
        return result ? success("文件已移至回收站") : error("操作失败");
    }

    /**
     * 从回收站恢复文件
     */
    @PostMapping("/{fileId}/restore")
    @PreAuthorize("hasPermission('media:file:edit')")
    @Operation(summary = "从回收站恢复", description = "从回收站恢复文件")
    public AjaxResult restoreFromTrash(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId) {
        
        boolean result = mediaFileService.restoreFromTrash(fileId, getUserId());
        return result ? success("文件已恢复") : error("操作失败");
    }

    /**
     * 永久删除文件
     */
    @DeleteMapping("/{fileId}")
    @PreAuthorize("hasPermission('media:file:delete')")
    @Operation(summary = "永久删除文件", description = "永久删除文件，不可恢复")
    public AjaxResult deleteFile(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId) {
        
        boolean result = mediaFileService.deleteMediaFile(fileId, getUserId());
        return result ? success("文件删除成功") : error("文件删除失败");
    }

    /**
     * 批量删除文件
     */
    @DeleteMapping("/batch")
    @PreAuthorize("hasPermission('media:file:delete')")
    @Operation(summary = "批量删除文件", description = "批量永久删除文件")
    public AjaxResult batchDeleteFiles(
            @Parameter(description = "文件ID列表", required = true) @RequestParam("fileIds") String fileIds) {
        
        if (StringUtils.isEmpty(fileIds)) {
            return error("请选择要删除的文件");
        }
        
        List<Long> fileIdList = Arrays.stream(fileIds.split(","))
                .map(Long::parseLong)
                .toList();
        
        boolean result = mediaFileService.batchDeleteMediaFiles(fileIdList, getUserId());
        return result ? success("批量删除成功") : error("批量删除失败");
    }

    /**
     * 生成文件分享链接
     */
    @PostMapping("/{fileId}/share")
    @PreAuthorize("hasPermission('media:file:share')")
    @Operation(summary = "生成分享链接", description = "生成文件分享链接")
    public AjaxResult generateShareLink(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId,
            @Parameter(description = "过期小时数") @RequestParam(value = "expireHours", defaultValue = "24") Integer expireHours) {
        
        String shareLink = mediaFileService.generateShareLink(fileId, getUserId(), expireHours);
        if (shareLink != null) {
            return success("分享链接生成成功", shareLink);
        } else {
            return error("分享链接生成失败");
        }
    }

    /**
     * 获取用户存储统计
     */
    @GetMapping("/storage/stats")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取存储统计", description = "获取用户存储空间使用统计")
    public AjaxResult getStorageStats() {
        Map<String, Object> stats = mediaFileService.getStorageStats(getUserId());
        return success(stats);
    }

    /**
     * 根据时间范围查询文件
     */
    @GetMapping("/by-time-range")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "按时间范围查询文件", description = "根据时间范围查询媒体文件")
    public TableDataInfo getFilesByTimeRange(
            @Parameter(description = "开始时间") @RequestParam(value = "startTime", required = false) String startTime,
            @Parameter(description = "结束时间") @RequestParam(value = "endTime", required = false) String endTime) {
        
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.selectMediaFilesByTimeRange(page, getUserId(), startTime, endTime);
        return getDataTable(result);
    }

    /**
     * 文件下载
     */
    @GetMapping("/{fileId}/download")
    @PreAuthorize("hasPermission('media:file:download')")
    @Operation(summary = "文件下载", description = "下载媒体文件")
    public void downloadFile(
            @Parameter(description = "文件ID", required = true) @PathVariable("fileId") Long fileId,
            HttpServletResponse response) {
        
        try {
            MediaFile mediaFile = mediaFileService.getById(fileId);
            if (mediaFile == null || !mediaFile.getUserId().equals(getUserId())) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 增加下载次数
            mediaFileService.incrementDownloadCount(fileId);
            
            // TODO: 实现文件下载逻辑
            // 这里需要读取物理文件并写入响应流
            
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 获取家庭公共文件
     */
    @GetMapping("/family/{familyId}")
    @PreAuthorize("hasPermission('media:file:view')")
    @Operation(summary = "获取家庭公共文件", description = "获取指定家庭的公共媒体文件")
    public TableDataInfo getFamilyFiles(
            @Parameter(description = "家庭ID", required = true) @PathVariable("familyId") Long familyId) {
        
        Page<MediaFile> page = PageUtils.buildPage();
        Page<MediaFile> result = mediaFileService.selectMediaFilesByFamilyId(page, familyId);
        return getDataTable(result);
    }
}